/*
 * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.ref;


/**
 * 软引用对象，垃圾收集器根据内存需求自行决定清除。
 * 软引用最常用于实现内存敏感的缓存。
 *
 * <p> 假设垃圾收集器在某个时间点确定一个对象是
 * <a href="package-summary.html#reachability">软可达的</a>。
 * 此时它可以选择原子地清除对该对象的所有软引用，以及对通过强引用链
 * 从该对象可达的任何其他软可达对象的所有软引用。
 * 同时或稍后，它将把那些已注册到引用队列的新清除的软引用加入队列。
 *
 * <p> 在虚拟机抛出<code>OutOfMemoryError</code>之前，
 * 保证所有对软可达对象的软引用都已被清除。
 * 否则，对于软引用被清除的时间或对不同对象的一组此类引用被清除的顺序，
 * 不施加任何约束。但是，鼓励虚拟机实现偏向于不清除最近创建或最近使用的软引用。
 *
 * <p> 此类的直接实例可用于实现简单缓存；
 * 此类或派生子类也可用于更大的数据结构中以实现更复杂的缓存。
 * 只要软引用的引用对象是强可达的，即实际在使用中，软引用就不会被清除。
 * 因此，复杂的缓存可以通过保持对那些条目的强引用来防止其最近使用的条目被丢弃，
 * 而让其余条目由垃圾收集器自行决定丢弃。
 *
 * @author   Mark Reinhold
 * @since    1.2
 */

public class SoftReference<T> extends Reference<T> {

    /**
     * 时间戳时钟，由垃圾收集器更新
     */
    static private long clock;

    /**
     * 每次调用get方法时更新的时间戳。VM在选择要清除的软引用时可能使用此字段，
     * 但不是必须这样做。
     */
    private long timestamp;

    /**
     * 创建一个引用给定对象的新软引用。新引用未注册到任何队列。
     *
     * @param referent 新软引用将引用的对象
     */
    public SoftReference(T referent) {
        super(referent);
        this.timestamp = clock;
    }

    /**
     * 创建一个引用给定对象并注册到给定队列的新软引用。
     *
     * @param referent 新软引用将引用的对象
     * @param q 引用要注册到的队列，如果不需要注册则为<tt>null</tt>
     *
     */
    public SoftReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
        this.timestamp = clock;
    }

    /**
     * 返回此引用对象的引用对象。如果此引用对象已被程序或垃圾收集器清除，
     * 则此方法返回<code>null</code>。
     *
     * @return   此引用所引用的对象，如果此引用对象已被清除则返回<code>null</code>
     */
    public T get() {
        T o = super.get();
        if (o != null && this.timestamp != clock)
            this.timestamp = clock;
        return o;
    }

}
